﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using Fcdbas.Common.File;
namespace Fcdbas.CodeBuilder.TemplateCode
{
    public class DBTemplate
   { 

    }
    public partial class TableStutrcTemplateBase : bTableStutrcTemplate
    {
    }

    public partial class MySqlDbCdbBase : bTableStutrcTemplate
    { 
  
    }

    public partial class MySqlPackageBase : bTableStutrcTemplate
    {

    }

    public partial class bTableStutrcTemplate
    {

        /// <summary>
        /// 实例化
        /// </summary>
        public static bTableStutrcTemplate instace = new bTableStutrcTemplate();

        public LogicUnit TableStutrcs
        {
            get;
            set;
        }


        public string TemplateReplace(string template, LogicUnit tableStutrc)
        {
            string _script = template
                    .Replace("<<<MODULE>>>", tableStutrc.ModelName)//模块
                    .Replace("<<<LUNAME>>>", tableStutrc.LuName)//逻辑单元
                    .Replace("<<<CRETABIND>>>", tableStutrc.GetCreateTableScript())//创建表脚本
                    .Replace("<<<VIEWNAME>>>", tableStutrc.View)//视图名称
                    .Replace("<<<VIEWCOL>>>", tableStutrc.GetCreateViewScript())  //创建视图脚本
                    .Replace("<<<TABNAME>>>", tableStutrc.TableName);//表名
           return _script;
        }


        public void InitTableStutrc(string xmlfile)
        {
            XmlNode xmlnode = (new XmlFile(xmlfile)).LoadXml();
            TableStutrcs = new LogicUnit();
            InitTableInfo(xmlnode, TableStutrcs);
            TableStutrcs.FieldList = getFieldList(xmlnode);
            //TableStutrcs = tableStutrc;
        }

        public string Serialize(Project curProject)
        {
           StringBuilder xml  =new StringBuilder("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
           xml.Append(string.Format("<Project Name=\"{0}\">",curProject.Name)).AppendLine();
           foreach (Moudle m in curProject.Model)
           {
               xml.Append(string.Format("<Model Id=\"{0}\"><Properties>", m.Id)).AppendLine();
               foreach (LogicUnit lu in m.LogicUnit)
               {
                   xml.Append(string.Format("<LogicalUnit LuName=\"{0}\" Package = \"{1}\" View=\"{2}\" Table=\"{3}\" State=\"{4}\" Namespace=\"{5}\">", lu.LuName,lu.Package,lu.View,lu.TableName,lu.State=="True"?"Y":"N","")).AppendLine();
                   xml.Append("<Attribute>");

                   foreach (FieldStutrc fs in lu.FieldList)
                   {
               xml.Append(string.Format("<Attribute Id=\"{0}\"        DataType=\"{1}\" Length=\"{2}\"   Format=\"{3}\" Prompt=\"{4}\"     Key=\"{5}\"  Required=\"{6}\"  Inserable=\"{7}\" LovFlag=\"{8}\" Updateable=\"{9}\"     ReferenceClass=\"{10}\"   ParentKeys=\"{11}\" OptionName=\"{12}\" OptionArg=\"{13}\"/>",fs.Id,fs.DataType,fs.Length,fs.Format,fs.Prompt,fs.pKey,fs.pRequired,fs.pInserable,fs.pLovFlag,fs.Updateable,fs.ReferenceClass,fs.ParentKeys,fs.OptionName,"")).AppendLine();
                   }

                   xml.Append("</Attribute>").AppendLine();
                   xml.Append("</LogicUnit>").AppendLine();

                   
               }

               xml.Append("</Properties></Model>").AppendLine();
           }

           xml.Append(string.Format("</Project>",curProject.Name)).AppendLine();

           return xml.ToString();
        }


        public void InitTableStutrc(LogicUnit tableStutrcs)
        {
            this.TableStutrcs = tableStutrcs;
        }

        private void InitTableInfo(XmlNode node,LogicUnit tableStutrc)
        {
            XmlNodeList FieldNodes = node.SelectNodes("Properties/LogicalUnit");
            tableStutrc.TableName = FieldNodes[0].Attributes["Table"].Value;
            tableStutrc.LuName = FieldNodes[0].Attributes["LuName"].Value;
            tableStutrc.Namespace = FieldNodes[0].Attributes["Namespace"].Value;
            tableStutrc.Package = FieldNodes[0].Attributes["Package"].Value;
            tableStutrc.State = FieldNodes[0].Attributes["Table"].Value;
            tableStutrc.View = FieldNodes[0].Attributes["View"].Value;
       }

        private IList<FieldStutrc> getFieldList(XmlNode node)
        {
            IList<FieldStutrc> _FieldList = new List<FieldStutrc>();
            XmlNodeList FieldNodes =node.SelectNodes("Properties/LogicalUnit[@LuName='DqRollManager']/Attribute/Attribute");
            for (int index = 0; index < FieldNodes.Count; index++)
            {
                FieldStutrc _FieldStutrc = new Fcdbas.CodeBuilder.TemplateCode.FieldStutrc();
                //string id = FieldNodes[index].Attributes["Id"].Value;
                _FieldStutrc.Id = getFieldInfo(FieldNodes[index], "Id");
                _FieldStutrc.Inserable = getFieldInfo(FieldNodes[index], "Inserable")=="Y";
                _FieldStutrc.Key = getFieldInfo(FieldNodes[index], "Key")=="Y";
                _FieldStutrc.Length = getFieldInfo(FieldNodes[index], "Length");
                _FieldStutrc.LovFlag = getFieldInfo(FieldNodes[index], "LovFlag")=="Y";
                _FieldStutrc.OptionName = getFieldInfo(FieldNodes[index], "OptionName");
                _FieldStutrc.ParentKeys = getFieldInfo(FieldNodes[index], "ParentKeys");
                //_FieldStutrc.Prompt = getFieldInfo(FieldNodes[index], "Prompt");
                _FieldStutrc.ReferenceClass = getFieldInfo(FieldNodes[index], "ReferenceClass");
                _FieldStutrc.Required = getFieldInfo(FieldNodes[index], "Required")=="Y";
                _FieldStutrc.Updateable = getFieldInfo(FieldNodes[index], "Updateable");
                _FieldStutrc.Format = getFieldInfo(FieldNodes[index], "Format");
                _FieldStutrc.DataType = getFieldInfo(FieldNodes[index], "DataType");
                _FieldList.Add(_FieldStutrc);
            }
            return _FieldList;
        }


        public string getFieldInfo(XmlNode node,string attr)
        {
            return node.Attributes[attr].Value;
        }

        public string getTableInfo(XmlNode node, string attr)
        {
            return node.Attributes[attr].Value;
        }

        public string SetNullToEmpty(string v)
        {
            return string.IsNullOrEmpty(v) ? "" : v;
        }


        /// <summary>
        /// 處理
        /// </summary>
        /// <param name="str"></param>
        /// <param name="splitStr"></param>
        /// <returns></returns>
        public static string GetUpperString(string str, string splitStr)
        {
            //string str = "MyNameIsJiang";
            if (str == null)
            {
                return "";
            }
            string _str = "";
            for (int index = 0; index < str.Length; index++)
            {
                var v = str.Substring(index, 1);
                 if (System.Text.RegularExpressions.Regex.IsMatch(v, "[A-Z]") && index != 0)
                {
                    if (index -1 >=0)
                    {
                        if (!System.Text.RegularExpressions.Regex.IsMatch(str.Substring(index-1, 1), "[A-Z]"))
                        {
                            _str = _str + splitStr;
                        }
                    }
                }
                _str = _str + v;
            }
            return _str;
        }
      
    }

    public class Project
    {
        public string Name
        {
            get;
            set;
        }

        public IList<Moudle> Model
        {
            get;
            set;
        }

        /// <summary>
        /// 
        /// </summary>
        public string DefaultCDBFile
        {
            get;
            set;
        }

        /// <summary>
        /// 
        /// </summary>
        public string DefaultPKGFile
        {
            get;
            set;
        }
    }

    public class Moudle
    {
        public string Id
        {
            get;
            set;
        }

        /// <summary>
        /// 指向的
        /// </summary>
        public string ProjectName
        {
            get;
            set;
        }

        public IList<LogicUnit> LogicUnit
        {
            get;
            set;
        }

        /// <summary>
        /// 
        /// </summary>
        public string DefaultCDBFile
        {
            get;
            set;
        }

        /// <summary>
        /// 
        /// </summary>
        public string DefaultPKGFile
        {
            get;
            set;
        }

    }

    public class LogicUnit
    {
        public LogicUnit()
        {
            FieldList = new List<FieldStutrc>();
        }
        //var xmlnode = (new iSun.Common.File.XmlFile("D:\\code.xml")).LoadXml();
        //string FN = xmlnode.SelectNodes("Properties/LogicalUnit[@LuName='DqRollManager']/Attribute/Attribute")[0].Attributes["Id"].Value;
        /// <summary>
        /// 项目名称
        /// </summary>
        public string ProjectName
        {
            get;
            set;
        }

        /// <summary>
        /// 模块名称
        /// </summary>
        public string ModelName
        {
            get;
            set;
        }

        /// <summary>
        /// 表名(逻辑单名称)
        /// </summary>
        public string TableName
        {
            get;
            set;
        }

        public string LuName
        {
            get;
            set;
        }

        public string Package
        {
            get;
            set;
        }

        public string View
        {
            get;
            set;
        }

        public string State
        {
            get;
            set;
        }

        public string Objid
        {
            get
            {
                return "Rowid";
            }
        }

        public string Objversion
        {
            get
            {
                return "Rowversion";
            }
        }

        public string Namespace
        {
            get;
            set;
        }

        public string PKGFile
        {
            get;
            set;
        }


        public string CDBFile
        {
            get;
            set;
        }

        /// <summary>
        /// 字段信息
        /// </summary>
        private IList<FieldStutrc> _FieldList;
        public IList<FieldStutrc> FieldList
        {
            get
            {
                return _FieldList;
            }
            set
            {
                _FieldList = value;
            }
        }


        #region 定义模版方法
        public string GetCreateViewScript()
        {
            StringBuilder _script = new StringBuilder("").AppendLine();
            foreach (FieldStutrc f in this.FieldList)
            {
                _script.Append(string.Format("    m.{0}{1},", f.Id.PadRight(40,' '),f.Id)).AppendLine();
           } 
            _script.Append("    m.rowid                          objid,").AppendLine();
            _script.Append("    date_format( m.rowversion, '%Y-%c-%d %H:%i:%s' )").AppendLine();
            return _script.ToString();
        }

        public string GetCreateTableScript()
        {
            StringBuilder _script = new StringBuilder(string.Format("CREATE TABLE IF NOT EXISTS {0}(", this.TableName)).AppendLine();
            foreach (FieldStutrc f in this.FieldList)
            {
                //_script.Append("s1.PadLeft(20,'*').Dump()(order_no      VARCHAR(12)   NOT NULL COMMENT 'FLAGS=KMI-L^DATATYPE=VARCHAR(12)^PROMPT=Order No^',");
                //order_amount                   DECIMAL(30,2) NULL     COMMENT 'FLAGS=A-IUL^DATATYPE=NUMBER/DECIMAL^PROMPT=Order Amount^',
                //delivery_date                  DATETIME      NOT NULL COMMENT 'FLAGS=AMINL^DATATYPE=DATE/DATETIME^PROMPT=Delivery Date^',
                switch (f.DataType)
                {
                    case "String":
                        _script.Append(string.Format("       {0}VARCHAR({1})   {2} Null COMMENT 'FLAGS=KMI-L^DATATYPE=VARCHAR({1})^PROMPT={3}^',", f.Id.PadRight(40, ' '), f.Length, (f.pRequired == "Y" || f.pRequired == "True") ? "Not " : "", f.Prompt)).AppendLine();
                        break;
                    case "Date":
                        _script.Append(string.Format("       {0}DATETIME   {1} Null COMMENT 'FLAGS=KMI-L^DATATYPE=DATE/DATETIME^PROMPT={2}^',", f.Id.PadRight(40, ' '), (f.pRequired == "Y" || f.pRequired == "True") ? "Not " : "", f.Prompt)).AppendLine();
                        break;
                    case "Number":
                        _script.Append(string.Format("       {0}DECIMAL(30,2) {1}  NULL     COMMENT 'FLAGS=A-IUL^DATATYPE=NUMBER/DECIMAL^PROMPT={2}^',", f.Id.PadRight(40, ' '), (f.pRequired == "Y" || f.pRequired == "True") ? "Not " : "", f.Prompt)).AppendLine();
                        break;
                    default:
                        _script.Append(string.Format("       {0}VARCHAR({1})   {2} Null COMMENT 'FLAGS=KMI-L^DATATYPE=VARCHAR({1})^PROMPT={3}^',", f.Id.PadRight(40, ' '), f.Length, (f.pRequired == "Y" || f.pRequired == "True") ? "Not " : "", f.Prompt)).AppendLine();
                        break;
                }
            } 
            _script.Append("        rowid                          VARCHAR(50)   NOT NULL,").AppendLine();
            _script.Append("        rowversion                     DATETIME      NOT NULL,").AppendLine();
            _script.Append(string.Format("        PRIMARY KEY ({0})",GetKeyWords(this.FieldList.Where(p => p.pKey == "Y" || p.pKey == "True").ToList<FieldStutrc>()))).AppendLine("        )");
            _script.Append("ENGINE = INNODB ").AppendLine();
            _script.Append("CHARACTER SET utf8").AppendLine();
            _script.Append("COLLATE utf8_general_ci");
            _script.Append(string.Format("COMMENT = 'LU={0}^PROMPT={1}^MODULE={2}^VIEW={3}^PKG={3}_API^';", this.LuName, bTableStutrcTemplate.GetUpperString(this.LuName, " "), this.ModelName, bTableStutrcTemplate.GetUpperString(this.LuName, "_")));
            return _script.ToString();
        }

        /// <summary>
        /// 获取关键字
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        public string GetKeyWords(IList<FieldStutrc> list)
        {
            return string.Join(",",list.Select(p => p.Id).ToArray());
        }
        #endregion
    }

    /// <summary>
    /// 
    /// </summary>
    public class FieldStutrc
    {
        //<Attribute Id="RegistId" DataType="Number" Length=""   Format="Unformatted" Prompt="Regist Id"  Key="Y"  Required="Y"  Inserable="Y" LovFlag="Y" Updateable="Not Allowed"  ReferenceClass="" ParentKeys="" OptionName="" OptionArg=""/>
        public string ReferenceClass
        {
            get;
            set;
        }

        public string ParentKeys
        {
            get;
            set;
        }

        public string OptionName
        {
            get;
            set;
        }

        public string OptionArg
        {
            get;
            set;
        }

        public string Id
        {
            get;
            set;
        }

        public string DataType
        {
            get;
            set;
        }

        public string Length
        {
            get;
            set;
        }

        public string Format
       { 
            get;
            set;
        }
        private string prompt;
        public string Prompt
        {
            get
            {
                if(string.IsNullOrEmpty(prompt))
                    prompt= ConverString(Id, " ");
                return prompt;
            }
            set
            {
                prompt =value;
            }
        }

        public string pKey
        {
            get
            {
                return Key ? "Y" : "N";
            }
        }

        public bool Key
        {
            get;
            set;
        }

        public string pRequired
        {
            get
            {
                return Required ? "Y" : "N";
            }
        }

        public bool Required
        {
            get;
            set;
        }



        public string pInserable
        {
            get
            {
                return Inserable ? "Y" : "N";
            }
        }

        public bool Inserable
        {
            get;
            set;
        }

        public string pLovFlag
        {
            get
            {
                return LovFlag ? "Y" : "N";
            }
        }

        public bool LovFlag
        {
            get;
            set;
        }

        public string pPublic
        {
            get
            {
                return Public ? "Y" : "N";
            }
        }

        public bool Public
        {
            get;
            set;
        }


        public string Updateable
        {
            get;
            set;
        }



        /// <summary>
        /// 字符轉換
        /// 將DropName轉換成Drop_Name 或Drop Name
        /// </summary>
        /// <param name="str"></param>
        /// <param name="splitStr"></param>
        /// <returns>STRING</returns>
        string ConverString(string str, string splitStr)
        {
            return bTableStutrcTemplate.GetUpperString(str, splitStr);
        }
    }
}
